package com.eian.boot.module.system.permission.service;

import com.eian.boot.common.core.enums.CommonEnum;
import com.eian.boot.common.core.exception.ExceptionHelper;
import com.eian.boot.common.core.utils.BeanCopierUtils;
import com.eian.boot.module.system.associations.role.permission.service.RolePermissionRelationService;
import com.eian.boot.module.system.permission.mapper.SysPermissionMapper;
import com.eian.boot.module.system.permission.model.dto.CreatePermissionRequest;
import com.eian.boot.module.system.permission.model.dto.PermissionDeleteRequest;
import com.eian.boot.module.system.permission.model.dto.PermissionQueryRequest;
import com.eian.boot.module.system.permission.model.dto.PermissionUpdateRequest;
import com.eian.boot.module.system.permission.model.entity.SysPermissionEntity;
import com.eian.boot.module.system.permission.model.vo.PermissionTreeVO;
import com.eian.boot.mybatis.core.service.BaseService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.eian.boot.common.constants.ErrorMessage.Permission;
import static com.eian.boot.table.Tables.sys_permission;

/**
 * 菜单权限表 服务层实现。
 *
 * @author alex.meng
 * @since 1.0.0
 */
@Service
@AllArgsConstructor
public class SysPermissionService extends BaseService<SysPermissionMapper, SysPermissionEntity> {
    private final RolePermissionRelationService rolePermissionRelationService;
    private final PermissionCacheService cacheService;

    /**
     * @author alex.meng
     * @description 创建菜单
     **/
    public void createPermission(CreatePermissionRequest params) {
        // 检查菜单编码是否重复
        boolean codeExists = this.queryChain().from(sys_permission)
                .where(sys_permission.code.eq(params.getCode()))
                .exists();
        ExceptionHelper.ifTrue(codeExists, Permission.CODE_EXIST);

        // 检查父权限是否存在
        if (ObjectUtils.isNotEmpty(params.getParentId()) && params.getParentId() > 0) {
            SysPermissionEntity parentPerm = this.getById(params.getParentId());
            ExceptionHelper.ifNull(parentPerm, Permission.PARENT_NOT_EXIST);
        }

        SysPermissionEntity permission = BeanCopierUtils.copy(params, SysPermissionEntity.class);
        // 手动映射title到name字段(DTO和Entity字段名不一致)
        permission.setName(params.getTitle());
        this.save(permission);
    }

    /**
     * @author alex.meng
     * @description 获取权限树形列表
     **/
    public List<PermissionTreeVO> getPermissionTree(PermissionQueryRequest params) {
        List<SysPermissionEntity> allPermission = this.queryChain()
                .from(sys_permission)
                .eq(SysPermissionEntity::getType, params.getType())
                .eq(SysPermissionEntity::getStatus, params.getStatus())
                .like(SysPermissionEntity::getName, params.getTitle())
                .like(SysPermissionEntity::getCode, params.getCode())
                .orderBy(SysPermissionEntity::getSortOrder).asc()
                .orderBy(SysPermissionEntity::getId).asc()
                .list();

        // 如果有搜索条件且结果不为空,直接返回扁平列表转换为VO
        boolean hasSearchCondition = ObjectUtils.isNotEmpty(params.getTitle()) || ObjectUtils.isNotEmpty(params.getCode());
        if (hasSearchCondition && !allPermission.isEmpty()) {
            return allPermission.stream().map(perm -> {
                PermissionTreeVO vo = BeanCopierUtils.copy(perm, PermissionTreeVO.class);
                vo.setTitle(perm.getName());
                return vo;
            }).collect(Collectors.toList());
        }
        
        return buildPermissionTree(allPermission, 0L);
    }

    private List<PermissionTreeVO> buildPermissionTree(List<SysPermissionEntity> allPermission, Long parentId) {
        List<PermissionTreeVO> result = new ArrayList<>();

        // 按父ID分组
        Map<Long, List<SysPermissionEntity>> permissionGroup = allPermission.stream()
                .collect(Collectors.groupingBy(perm -> perm.getParentId() == null ? 0L : perm.getParentId()));

        List<SysPermissionEntity> currentLevelPermissions = permissionGroup.get(parentId);
        if (currentLevelPermissions != null) {
            for (SysPermissionEntity perm : currentLevelPermissions) {
                PermissionTreeVO tmp = BeanCopierUtils.copy(perm, PermissionTreeVO.class);
                // 手动映射name到title字段(Entity和VO字段名不一致)
                tmp.setTitle(perm.getName());
                // 递归构建子菜单
                List<PermissionTreeVO> children = buildPermissionTree(allPermission, perm.getId());
                tmp.setChildren(children);
                result.add(tmp);
            }
        }

        return result;
    }

    /**
     * @author alex.meng
     * @description 获取权限详情
     **/
    public PermissionTreeVO getDetail(Long permId) {
        SysPermissionEntity permission = this.getById(permId);
        ExceptionHelper.ifNull(permission, Permission.NOT_EXIST);
        PermissionTreeVO vo = BeanCopierUtils.copy(permission, PermissionTreeVO.class);
        // 手动映射name到title字段(Entity和VO字段名不一致)
        vo.setTitle(permission.getName());
        return vo;
    }

    /**
     * @author alex.meng
     * @description 更新权限信息
     **/
    public void update(PermissionUpdateRequest params) {
        SysPermissionEntity permission = this.getById(params.getId());
        ExceptionHelper.ifNull(permission, Permission.NOT_EXIST);

        BeanCopierUtils.copy(params, permission);
        // 手动映射title到name字段(DTO和Entity字段名不一致)
        if (params.getTitle() != null) {
            permission.setName(params.getTitle());
        }
        this.updateById(permission);

        cacheService.clearAllUserCache();
    }

    /**
     * @author alex.meng
     * @description 删除权限
     **/
    @Transactional(rollbackFor = Exception.class)
    public void delete(PermissionDeleteRequest params) {
        SysPermissionEntity permission = this.getById(params.getId());
        ExceptionHelper.ifNull(permission, Permission.NOT_EXIST);

        long childCount = this.queryChain()
                .from(sys_permission)
                .where(sys_permission.parent_id.eq(params.getId()))
                .count();
        ExceptionHelper.ifTrue(childCount > 0, Permission.HAS_CHILDREN);

        if (ObjectUtils.isNotEmpty(params.getForce()) && params.getForce().equals(CommonEnum.YES.getValue())) {
            // 强制删除：清理权限与所有角色的关系（会触发事件清理缓存）
            rolePermissionRelationService.cascadeDeleteByPermissionId(permission.getId());
        } else {
            // 检查是否有角色绑定
            boolean hasBind = rolePermissionRelationService.checkPermissionHasRoles(permission.getId());
            ExceptionHelper.ifTrue(hasBind, Permission.HAS_BIND);
        }

        this.removeById(permission);

        cacheService.clearAllUserCache();
    }
}